

/**
 * @file CorrectObservables.cpp
 * This class corrects observables from effects such as antenna excentricity,
 * difference in phase centers, offsets due to tide effects, etc.
 */

//============================================================================
//
//  This file is part of GPSTk, the GPS Toolkit.
//
//  The GPSTk is free software; you can redistribute it and/or modify
//  it under the terms of the GNU Lesser General Public License as published
//  by the Free Software Foundation; either version 2.1 of the License, or
//  any later version.
//
//  The GPSTk is distributed in the hope that it will be useful,
//  but WITHOUT ANY WARRANTY; without even the implied warranty of
//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//  GNU Lesser General Public License for more details.
//
//  You should have received a copy of the GNU Lesser General Public
//  License along with GPSTk; if not, write to the Free Software Foundation,
//  Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
//
//  Dagoberto Salazar - gAGE ( http://www.gage.es ). 2007, 2008, 2009, 2011
//
//============================================================================


#include "CorrectObservables.hpp"

using namespace std;

#define debug 1

namespace gpstk
{

    // Return a string identifying this object.
    std::string CorrectObservables::getClassName() const
    { return "CorrectObservables"; }



      /* Return a satTypeValueMap object, adding the new data generated
       * when calling this object.
       *
       * @param time      Epoch corresponding to the data.
       * @param gData     Data object holding the data.
       */
    satTypeValueMap& CorrectObservables::Process( const CommonTime& time,
                                                  satTypeValueMap& gData )
        noexcept(false)
    {

        try
        {

            // Compute station latitude and longitude
            double lat( nominalPos.geodeticLatitude() );
            double lon( nominalPos.longitude() );

            // Define station position as a Triple, in ECEF
            Triple staPos( nominalPos.getX(),
                           nominalPos.getY(),
                           nominalPos.getZ() );

            // Compute initial displacement vectors, in meters [UEN]
            Triple initialBias( tide + monument );

            if(debug)
            {
               cout << "tide:" << endl;
               cout << tide << endl;
               cout << "monument:" << endl;
               cout << monument << endl;
            }

            Triple dispL1( initialBias );
            Triple dispL2( initialBias );
            Triple dispL5( initialBias );
            Triple dispL6( initialBias );
            Triple dispL7( initialBias );
            Triple dispL8( initialBias );
            Triple dispL9( initialBias );


            // Define a Triple that will hold satellite position, in ECEF
            Triple satPos(0.0, 0.0, 0.0);

            SatIDSet satRejectedSet;

            // Loop through all the satellites
            for(satTypeValueMap::iterator it = gData.begin();
                it != gData.end();
                ++it)
            {
                SatID sat( it->first );

                 /// Position of antenna L1 phase center with respect to ARP ([UEN]).
                Triple L1PhaseCenter( 0.0, 0.0, 0.0 );
                Triple L2PhaseCenter( 0.0, 0.0, 0.0 );
                Triple L5PhaseCenter( 0.0, 0.0, 0.0 );
                Triple L6PhaseCenter( 0.0, 0.0, 0.0 );
                Triple L7PhaseCenter( 0.0, 0.0, 0.0 );
                Triple L8PhaseCenter( 0.0, 0.0, 0.0 );
                Triple L9PhaseCenter( 0.0, 0.0, 0.0 );

                Triple zeroTrip(0.0, 0.0, 0.0);

                // Check if we have a valid Antenna object
                if( antenna.isValid() )
                {
                    // Compute phase center offsets
                    if( sat.system == SatelliteSystem::GPS )
                    {
                        try
                        {
                            L1PhaseCenter = antenna.getAntennaEccentricity( Antenna::G01 );
                        }
                        catch(Exception& e)
                        {
                            L1PhaseCenter = zeroTrip;
                        }

                        try
                        {
                            L2PhaseCenter = antenna.getAntennaEccentricity( Antenna::G02 );
                        }
                        catch(Exception& e)
                        {
                            L2PhaseCenter = zeroTrip;
                        }

                        try
                        {
                            L5PhaseCenter = antenna.getAntennaEccentricity( Antenna::G05 );
                        }
                        catch(Exception& e)
                        {
                            L5PhaseCenter = zeroTrip;
                        }
                    }
                    else if( sat.system == SatelliteSystem::GLONASS )
                    {
                        try
                        {
                        L1PhaseCenter = antenna.getAntennaEccentricity( Antenna::R01 );
                        }
                        catch(Exception& e)
                        {
                            L1PhaseCenter = zeroTrip;
                        }

                        try
                        {
                            L2PhaseCenter = antenna.getAntennaEccentricity( Antenna::R02 );
                        }
                        catch(Exception& e)
                        {
                            L2PhaseCenter = zeroTrip;
                        }
                    }
                    else if( sat.system == SatelliteSystem::Galileo )
                    {
                        try
                        {
                            L1PhaseCenter = antenna.getAntennaEccentricity( Antenna::E01 );
                        }
                        catch(Exception& e)
                        {
                            L1PhaseCenter = zeroTrip;
                        }

                        try
                        {
                            L5PhaseCenter = antenna.getAntennaEccentricity( Antenna::E05 );
                        }
                        catch(Exception& e)
                        {
                            L5PhaseCenter = zeroTrip;
                        }

                        try
                        {
                            L7PhaseCenter = antenna.getAntennaEccentricity( Antenna::E07 );
                        }
                        catch(Exception& e)
                        {
                            L7PhaseCenter = zeroTrip;
                        }

                        try
                        {
                            L8PhaseCenter = antenna.getAntennaEccentricity( Antenna::E08 );
                        }
                        catch(Exception& e)
                        {
                            L8PhaseCenter = zeroTrip;
                        }
                        try {
                            L6PhaseCenter = antenna.getAntennaEccentricity( Antenna::E06 );
                        }
                        catch(Exception& e) {
                            L6PhaseCenter = zeroTrip;
                        }
                    }
                    else if( sat.system == SatelliteSystem::QZSS )
                    {
                        try {
                            L1PhaseCenter = antenna.getAntennaEccentricity(Antenna::J01 );
                        }
                        catch(Exception& e) {
                            L1PhaseCenter = zeroTrip;
                        }
                        try {
                            L2PhaseCenter = antenna.getAntennaEccentricity(Antenna::J02 );
                        }
                        catch(Exception& e) {
                            L2PhaseCenter = zeroTrip;
                        }
                        try {
                            L5PhaseCenter = antenna.getAntennaEccentricity(Antenna::J05 );
                        }
                        catch(Exception& e) {
                            L5PhaseCenter = zeroTrip;
                        }
                        try {
                            L6PhaseCenter = antenna.getAntennaEccentricity(Antenna::J06 );
                        }
                        catch(Exception& e) {
                            L2PhaseCenter = zeroTrip;
                        }
                    }
                    else if( sat.system == SatelliteSystem::BDS )
                    {
                        try
                        {
                            L2PhaseCenter = antenna.getAntennaEccentricity(Antenna::C02 );
                        }
                        catch(Exception& e)
                        {
                            L2PhaseCenter = zeroTrip;
                        }
                        try
                        {
                            L6PhaseCenter = antenna.getAntennaEccentricity(Antenna::C06 );
                        }
                        catch(Exception& e)
                        {
                            L6PhaseCenter = zeroTrip;
                        }
                        try
                        {
                            L7PhaseCenter = antenna.getAntennaEccentricity(Antenna::C07 );
                        }
                        catch(Exception& e)
                        {
                            L7PhaseCenter = zeroTrip;
                        }
                    }
                    else if( sat.system == SatelliteSystem::IRNSS )
                    {
                        try
                        {
                            L5PhaseCenter = antenna.getAntennaEccentricity(Antenna::I05 );
                            L9PhaseCenter = antenna.getAntennaEccentricity(Antenna::I09 );
                        }
                        catch(Exception& e)
                        {
                            L5PhaseCenter = zeroTrip;
                            L7PhaseCenter = zeroTrip;
                        }
                    }
                }


                if( ( (*it).second.find(TypeID::satXECF) == (*it).second.end() ) ||
                    ( (*it).second.find(TypeID::satYECF) == (*it).second.end() ) ||
                    ( (*it).second.find(TypeID::satZECF) == (*it).second.end() ) )
                {
                    satRejectedSet.insert( sat );
                    continue;
                }
                else
                {
                    // Get satellite position out of GDS
                    satPos[0] = (*it).second[TypeID::satXECF];
                    satPos[1] = (*it).second[TypeID::satYECF];
                    satPos[2] = (*it).second[TypeID::satZECF];
                }


                // Declare the variables where antenna PC variations
                // will be stored.
                Triple L1Var( 0.0, 0.0, 0.0 );
                Triple L2Var( 0.0, 0.0, 0.0 );
                Triple L5Var( 0.0, 0.0, 0.0 );
                Triple L6Var( 0.0, 0.0, 0.0 );
                Triple L7Var( 0.0, 0.0, 0.0 );
                Triple L8Var( 0.0, 0.0, 0.0 );
                Triple L9Var( 0.0, 0.0, 0.0 );

                // Check if we have a valid Antenna object
                if( antenna.isValid() )
                {
                    // Check if we have elevation information
                    if( (*it).second.find(TypeID::elevation) != (*it).second.end() )
                    {

                        // Get elevation value
                        double elev( (*it).second[TypeID::elevation] );

                        // Check if azimuth is also required
                        if( !useAzimuth )
                        {
                            // In this case, use methods that only need elevation
                            try
                            {
                                // Compute phase center variation values
                                if( sat.system == SatelliteSystem::GPS )
                                {
                                    try {
                                        L1Var = antenna.getAntennaPCVariation(Antenna::G01, elev );
                                    }
                                    catch(Exception& e)
                                    {
                                        L1Var = zeroTrip;
                                    }
                                    try {
                                        L2Var = antenna.getAntennaPCVariation(Antenna::G02, elev );
                                    }
                                    catch(Exception& e)
                                    {
                                        L2Var = zeroTrip;
                                    }
                                    try {
                                        L5Var = antenna.getAntennaPCVariation(Antenna::G05, elev );
                                    }
                                    catch(Exception& e)
                                    {
                                        L5Var = zeroTrip;
                                    }
                                }
                                else if( sat.system == SatelliteSystem::GLONASS )
                                {
                                    try {
                                        L1Var = antenna.getAntennaPCVariation(Antenna::R01, elev );
                                    }
                                    catch(Exception& e)
                                    {
                                        L1Var = zeroTrip;
                                    }
                                    try {
                                        L2Var = antenna.getAntennaPCVariation(Antenna::R02, elev );
                                    }
                                    catch(Exception& e)
                                    {
                                        L2Var = zeroTrip;
                                    }
                                }
                                else if( sat.system == SatelliteSystem::Galileo ) // no PCV available
                                {
                                    try {
                                        L1Var = antenna.getAntennaPCVariation(Antenna::E01, elev );
                                    }
                                    catch(Exception& e) {
                                        L1Var = zeroTrip;
                                    }
                                    try {
                                        L5Var = antenna.getAntennaPCVariation(Antenna::E05, elev );
                                    }
                                    catch(Exception& e) {
                                        L5Var = zeroTrip;
                                    }
                                    try
                                    {
                                        L6Var = antenna.getAntennaPCVariation(Antenna::E06, elev );
                                    }
                                    catch(Exception& e) {
                                        L6Var = zeroTrip;
                                    }

                                    try {
                                        L7Var = antenna.getAntennaPCVariation(Antenna::E07, elev );
                                    }
                                    catch(Exception& e) {
                                        L7Var = zeroTrip;
                                    }
                                    try {
                                        L8Var = antenna.getAntennaPCVariation(Antenna::E08, elev );
                                    }
                                    catch(Exception& e) {
                                        L8Var = zeroTrip;
                                    }
                                }
                                else if( sat.system == SatelliteSystem::BDS ) // no PCV available
                                {
                                    try {
                                        L2Var = antenna.getAntennaPCVariation(Antenna::C02, elev );
                                    }
                                    catch(Exception& e) {
                                        L2Var = zeroTrip;
                                    }
                                    try {
                                        L6Var = antenna.getAntennaPCVariation(Antenna::C06, elev );
                                    }
                                    catch(Exception& e) {
                                        L6Var = zeroTrip;
                                    }
                                    try {
                                        L7Var = antenna.getAntennaPCVariation(Antenna::C07, elev );
                                    }
                                    catch(Exception& e) {
                                        L7Var = zeroTrip;
                                    }
                                }
                                else if( sat.system == SatelliteSystem::QZSS ) // no PCV available
                                {
                                    try {
                                        L1Var = antenna.getAntennaPCVariation(Antenna::J01, elev );
                                        L2Var = antenna.getAntennaPCVariation(Antenna::J02, elev );
                                        L5Var = antenna.getAntennaPCVariation(Antenna::J05, elev );
                                        L6Var = antenna.getAntennaPCVariation(Antenna::J06, elev );
                                    }
                                    catch(Exception& e) {
                                        L1Var = zeroTrip;
                                        L2Var = zeroTrip;
                                        L5Var = zeroTrip;
                                        L6Var = zeroTrip;
                                    }

                                }
                                else if( sat.system == SatelliteSystem::IRNSS ) // no PCV available
                                {
                                    try { 
                                        L5Var = antenna.getAntennaPCVariation(Antenna::I05, elev );
                                        L9Var = antenna.getAntennaPCVariation(Antenna::I09, elev );
                                    }
                                    catch(Exception& e) {
                                        L5Var = zeroTrip;
                                        L9Var = zeroTrip;
                                    }
                                }
                            }
                            catch(InvalidRequest& ir)
                            {
                                // Throw an exception if something unexpected
                                // happens
                                ProcessingException e( getClassName() + ":"
                                        + "Unexpected problem found when trying to "
                                        + "compute antenna offsets" );

                                GPSTK_THROW(e);
                            }
                        }
                        else
                        {
                            // Check if we have azimuth information
                            if( (*it).second.find(TypeID::azimuth) !=
                                                            (*it).second.end() )
                            {

                                // Get azimuth value
                                double azim( (*it).second[TypeID::azimuth] );

                                // Use a gentle fallback mechanism to get antenna
                                // phase center variations
                                try
                                {
                                    // Compute phase center variation values
                                    if( sat.system == SatelliteSystem::GPS )
                                    {
                                        L1Var = antenna.getAntennaPCVariation(Antenna::G01, elev, azim );
                                        L2Var = antenna.getAntennaPCVariation(Antenna::G02, elev, azim );
                                        L5Var = antenna.getAntennaPCVariation(Antenna::G05, elev, azim );
                                    }
                                    else if( sat.system == SatelliteSystem::GLONASS )
                                    {
                                        L1Var = antenna.getAntennaPCVariation(Antenna::R01, elev, azim );
                                        L2Var = antenna.getAntennaPCVariation(Antenna::R02, elev, azim );
                                    }
                                    else if( sat.system == SatelliteSystem::Galileo ) // no PCV available
                                    {
//                                      L1Var = antenna.getAntennaPCVariation(Antenna::E01, elev, azim );
//                                      L5Var = antenna.getAntennaPCVariation(Antenna::E05, elev, azim );
//                                      L6Var = antenna.getAntennaPCVariation(Antenna::E06, elev, azim );
//                                      L7Var = antenna.getAntennaPCVariation(Antenna::E07, elev, azim );
//                                      L8Var = antenna.getAntennaPCVariation(Antenna::E08, elev, azim );
                                    }
                                    else if( sat.system == SatelliteSystem::QZSS ) // no PCV available
                                    {
//                                      L1Var = antenna.getAntennaPCVariation(Antenna::J01, elev, azim );
//                                      L2Var = antenna.getAntennaPCVariation(Antenna::J02, elev, azim );
//                                      L5Var = antenna.getAntennaPCVariation(Antenna::J05, elev, azim );
//                                      L6Var = antenna.getAntennaPCVariation(Antenna::J06, elev, azim );
                                    }
                                    else if( sat.system == SatelliteSystem::BDS ) // no PCV available
                                    {
//                                      L2Var = antenna.getAntennaPCVariation(Antenna::C02, elev, azim );
//                                      L6Var = antenna.getAntennaPCVariation(Antenna::C06, elev, azim );
//                                      L7Var = antenna.getAntennaPCVariation(Antenna::C07, elev, azim );
                                    }
                                    else if( sat.system == SatelliteSystem::IRNSS ) // no PCV available
                                    {
//                                      L5Var = antenna.getAntennaPCVariation(Antenna::I05, elev, azim );
//                                      L9Var = antenna.getAntennaPCVariation(Antenna::I09, elev, azim );
                                    }
                                }
                                catch(InvalidRequest& ir)
                                {
                                    // We  "graceful degrade" to a simpler mechanism
                                    try
                                    {
                                        // Compute phase center variation values
                                        if( sat.system == SatelliteSystem::GPS )
                                        {
                                            L1Var = antenna.getAntennaPCVariation(Antenna::G01, elev );
                                            L2Var = antenna.getAntennaPCVariation(Antenna::G02, elev );
                                            L5Var = antenna.getAntennaPCVariation(Antenna::G05, elev );
                                        }
                                        else if( sat.system == SatelliteSystem::GLONASS )
                                        {
                                            L1Var = antenna.getAntennaPCVariation(Antenna::R01, elev );
                                            L2Var = antenna.getAntennaPCVariation(Antenna::R02, elev );
                                        }
                                        else if( sat.system == SatelliteSystem::Galileo )
                                        {
//                                          L1Var = antenna.getAntennaPCVariation(Antenna::E01, elev );
//                                          L5Var = antenna.getAntennaPCVariation(Antenna::E05, elev );
//                                          L6Var = antenna.getAntennaPCVariation(Antenna::E06, elev );
//                                          L7Var = antenna.getAntennaPCVariation(Antenna::E07, elev );
//                                          L8Var = antenna.getAntennaPCVariation(Antenna::E08, elev );
                                        }
                                        else if( sat.system == SatelliteSystem::QZSS )
                                        {
//                                          L1Var = antenna.getAntennaPCVariation(Antenna::J01, elev );
//                                          L2Var = antenna.getAntennaPCVariation(Antenna::J02, elev );
//                                          L5Var = antenna.getAntennaPCVariation(Antenna::J05, elev );
//                                          L6Var = antenna.getAntennaPCVariation(Antenna::J06, elev );
                                        }
                                        else if( sat.system == SatelliteSystem::BDS )
                                        {
//                                          L1Var = antenna.getAntennaPCVariation(Antenna::C01, elev );
//                                          L2Var = antenna.getAntennaPCVariation(Antenna::C02, elev );
                                        }
                                        else if( sat.system == SatelliteSystem::IRNSS )
                                        {
//                                          L5Var = antenna.getAntennaPCVariation(Antenna::I05, elev );
//                                          L9Var = antenna.getAntennaPCVariation(Antenna::I09, elev );
                                        }
                                    }
                                    catch(InvalidRequest& ir)
                                    {
                                        // Throw an exception if something unexpected
                                        // happens
                                        ProcessingException e( getClassName() + ":"
                                            + "Unexpected problem found when trying to "
                                            + "compute antenna offsets" );

                                        GPSTK_THROW(e);
                                    }
                                }
                            }
                            else
                            {
                                // Throw an exception if something unexpected happens
                                ProcessingException e( getClassName() + ":"
                                    + "Azimuth information could not be found, "
                                    + "so antenna PC offsets can not be computed");

                                GPSTK_THROW(e);

                            }  // End of 'if( (*it).second.find(TypeID::azimuth) !=...'

                        }  // End of 'if( !useAzimuth )'
                    }
                    else
                    {
                        // Throw an exception if there is no elevation data
                        ProcessingException e( getClassName() + ":"
                            + "Elevation information could not be found, "
                            + "so antenna PC offsets can not be computed" );

                        GPSTK_THROW(e);

                    }  // End of 'if( (*it).second.find(TypeID::elevation) != ...'

                }  // End of 'if( antenna.isValid() )...'




                // Compute vector station-satellite, in ECF
                Triple ray(staPos - satPos);

                ray = ray.unitVector();

                // Rotate vector ray to UEN reference frame
                ray = (ray.R3(lon)).R2(-lat);

                // Convert ray to an unitary vector
                ray = ray.unitVector();

                // Update displacement vectors with current phase centers
                Triple dL1( dispL1 + L1PhaseCenter );
                Triple dL2( dispL2 + L2PhaseCenter );
                Triple dL5( dispL5 + L5PhaseCenter );
                Triple dL6( dispL6 + L6PhaseCenter );
                Triple dL7( dispL7 + L7PhaseCenter );
                Triple dL8( dispL8 + L8PhaseCenter );

                if(debug)
                {
                   cout << "dL1:" << endl;
                   cout <<  dL1  << endl;
                }

                // Compute corrections = displacement vectors components
                // along ray direction.
                double corr1( 0.0 );
                double corr2( 0.0 );
                double corr5( 0.0 );
                double corr6( 0.0 );
                double corr7( 0.0 );
                double corr8( 0.0 );

                if(sat.system == SatelliteSystem::GPS)
                {
                    corr1 = dL1.dot(ray) + L1Var[0];
                    corr2 = dL2.dot(ray) + L2Var[0];
                    corr5 = dL5.dot(ray) + L5Var[0];

                    (*it).second[TypeID::rcvCorr1] = corr1 ;
                    (*it).second[TypeID::rcvCorr2] = corr2 ;
                    (*it).second[TypeID::rcvCorr5] = corr5 ;
                }
                else if(sat.system == SatelliteSystem::Galileo)
                {
                    corr1 = dL1.dot(ray) + L1Var[0];
                    corr2 = dL2.dot(ray) + L2Var[0];
                    corr5 = dL5.dot(ray) + L5Var[0];
                    corr7 = dL7.dot(ray) + L7Var[0];
                    corr8 = dL8.dot(ray) + L8Var[0];
                    corr6 = dL6.dot(ray) + L6Var[0];

                    (*it).second[TypeID::rcvCorr1] = corr1 ;
                    (*it).second[TypeID::rcvCorr2] = corr2 ;
                    (*it).second[TypeID::rcvCorr5] = corr5 ;
                    (*it).second[TypeID::rcvCorr7] = corr7 ;
                    (*it).second[TypeID::rcvCorr8] = corr8 ;
                    (*it).second[TypeID::rcvCorr6] = corr6 ;

                }
                else if(sat.system == SatelliteSystem::GLONASS)
                {
                    corr1 = dL1.dot(ray) + L1Var[0];
                    corr2 = dL2.dot(ray) + L2Var[0];

                    (*it).second[TypeID::rcvCorr1] = corr1 ;
                    (*it).second[TypeID::rcvCorr2] = corr2 ;

                }
                else if(sat.system == SatelliteSystem::BDS)
                {
                    corr2 = dL2.dot(ray) + L2Var[0];
                    corr7 = dL7.dot(ray) + L7Var[0];
                    corr6 = dL6.dot(ray) + L6Var[0];

                    (*it).second[TypeID::rcvCorr2] = corr2 ;
                    (*it).second[TypeID::rcvCorr7] = corr7 ;
                    (*it).second[TypeID::rcvCorr6] = corr6 ;
                }
                else if(sat.system == SatelliteSystem::QZSS)
                {
                    corr1 = dL1.dot(ray) + L1Var[0];
                    corr2 = dL2.dot(ray) + L2Var[0];
                    corr5 = dL5.dot(ray) + L5Var[0];
                    corr6 = dL6.dot(ray) + L6Var[0];

                    (*it).second[TypeID::rcvCorr1] = corr1 ;
                    (*it).second[TypeID::rcvCorr2] = corr2 ;
                    (*it).second[TypeID::rcvCorr5] = corr5 ;
                    (*it).second[TypeID::rcvCorr6] = corr6 ;
                }

            } // End of 'for(satTypeValueMap::iterator = it, ...)'

            firstTime = false;

            // Remove satellites with missing data
            gData.removeSatID(satRejectedSet);

            return gData;

        }
        catch(Exception& u)
        {
            // Throw an exception if something unexpected happens
            ProcessingException e( getClassName() + ":" + u.what() );
            GPSTK_THROW(e);
        }

    }  // End of method 'CorrectObservables::Process()'

    void CorrectObservables::Process(gnssRinex& gData)
        noexcept(false)
    {

        antModel = gData.header.srcAntType ;

                // Must set antenna file first
        if(pAntexReader == NULL)
        {
            ProcessingException e("CorrectObservables::No antenna file!");
            cout << e << endl;
            exit(-1);
        }

        try
        {
            antenna = pAntexReader->getAntenna(antModel);
        }
        catch(ObjectNotFound& notFound)
        {
            // new antenna model
            if(antModel.size() == 20)
            {
                antModel.replace(16,4,"NONE");
            }
            else
            {
                // Some stations has special format, so we just erase the
                // last 'NONE' and find the antenna.2017-04-17
                antModel.erase(antModel.size()-4,4);
            }

            // new receiver antenna with new antenna model
            try
            {
                antenna = pAntexReader->getAntenna( antModel );
            }
            catch(ObjectNotFound& notFound)
            {
                GPSTK_RETHROW(notFound);
            }
        }

        monument   = gData.header.srcMonument;
        nominalPos = gData.header.srcPos;

        SourceID source(gData.header.source);
        string station = source.sourceName;

        if(pStaTides != NULL)
        {
           pStaTides->setNominalPosition( nominalPos );
           tide = pStaTides->getTides( gData.header.epoch, station);
        }
        else
        {
           tide = gData.header.srcTide;
        }

        Process( gData.header.epoch, gData.body );


    } // End of method 'CorrectObservables::Process()'

     /** Return a sourceRinex object, adding the new data generated when
      *  calling this object.
      *
      * @param gData    Data object holding the data.
      */
    void CorrectObservables::Process(commonHeader& comHeader, gnssRinex& gData)
        noexcept(false)
    {

        pAntexReader = comHeader.pAntexReader;

        antModel = gData.header.srcAntType ;

                // Must set antenna file first
        if(pAntexReader == NULL)
        {
            ProcessingException e("CorrectObservables::No antenna file!");
            cerr << e << endl;
            exit(-1);
        }

        try
        {
            antenna = pAntexReader->getAntenna(antModel);
        }
        catch(ObjectNotFound& notFound)
        {
            // new antenna model
            if(antModel.size() == 20)
            {
                antModel.replace(16,4,"NONE");
            }
            else
            {
                // Some stations has special format, so we just erase the
                // last 'NONE' and find the antenna.2017-04-17
                antModel.erase(antModel.size()-4,4);
            }

            // new receiver antenna with new antenna model
            try
            {
                antenna = pAntexReader->getAntenna( antModel );
            }
            catch(ObjectNotFound& notFound)
            {
                GPSTK_RETHROW(notFound);
            }
        }

        monument   = gData.header.srcMonument;
        nominalPos = gData.header.srcPos;

        SourceID source(gData.header.source);
        string station = source.sourceName;

        if(pStaTides != NULL)
        {
           pStaTides->setNominalPosition( nominalPos );
           tide = pStaTides->getTides( gData.header.epoch, station);
        }
        else
        {
           tide = gData.header.srcTide;
        }

        Process( gData.header.epoch, gData.body );


    } // End of method 'CorrectObservables::Process()'

     /** Return a sourceRinex object, adding the new data generated when
      *  calling this object.
      *
      * @param gData    Data object holding the data.
      */
    void CorrectObservables::Process(commonHeader& comHeader,sourceRinex& gData)
        noexcept(false)
    {

        pMSCStore          = comHeader.pMSCStore;

        sourceMonumentData = gData.header.srcMonumentData;
        sourceAntennaData  = gData.header.srcAntennaData;
        sourceTideData     = gData.header.srcTideData;
        


        SourceIDSet sourceRejectedSet;

        CommonTime epoch( gData.header.epoch );
        epoch.setTimeSystem( TimeSystem::Unknown );

        for( sourceDataMap::iterator sdmIt = gData.body.begin();
             sdmIt != gData.body.end();
             ++sdmIt )
        {
            SourceID source( sdmIt->first );

            if( sourceMonumentData.find(source) == sourceMonumentData.end() ||
                sourceAntennaData.find(source) == sourceAntennaData.end() )
            {
                cerr << "don't find source in sourceMonumentData and sourceAntennaData" << endl;
                exit(-1);
                sourceRejectedSet.insert( source );
            }


            monument = sourceMonumentData[source];
            antenna = sourceAntennaData[source];


            if(pMSCStore == NULL)
            {
                cerr << "no msc data" << endl;
                exit(-1);
            }

            string station( source.sourceName );
            MSCData mscData;
            try
            {
                mscData = pMSCStore->findMSC(station,epoch);
            }
            catch(...)
            {
                sourceRejectedSet.insert( source );
                continue;
            }

            nominalPos = mscData.coordinates;

            if(pStaTides != NULL)
            {
               pStaTides->setNominalPosition( nominalPos );
               tide = pStaTides->getTides( epoch, station);
            }
            else
            {
               tide = sourceTideData[source];
            }

            Process( gData.header.epoch, sdmIt->second );
        }

        gData.removeSourceID( sourceRejectedSet );


    } // End of method 'CorrectObservables::Process()'


}  // End of namespace gpstk
